quartz: Emulate root window as 1x1 bitmap
authorKristian Rietveld <kris@gtk.org>
Mon, 4 Oct 2010 09:43:16 +0000 (11:43 +0200)
committerKristian Rietveld <kris@gtk.org>
Mon, 4 Oct 2010 09:45:47 +0000 (11:45 +0200)
We subclass GdkWindowImplQuartz into a new GdkRootWindowImplQuartz,
and override the get_context method in order to do this cleanly.
Also made release_context a virtual method, since the root window has
to release its CGContextRef differently compared to normal windows.

gdk/quartz/gdkdrawable-quartz.c
gdk/quartz/gdkdrawable-quartz.h
gdk/quartz/gdkwindow-quartz.c
gdk/quartz/gdkwindow-quartz.h

index 8c6a141fa22534254f9e57c3ef259de993e0750f..b19913675b4954e55a57b6a91cfdee07c0f2b261 100644 (file)
@@ -167,6 +167,20 @@ gdk_quartz_drawable_get_context (GdkDrawable *drawable,
   return GDK_DRAWABLE_IMPL_QUARTZ_GET_CLASS (drawable)->get_context (drawable, antialias);
 }
 
+void
+gdk_quartz_drawable_release_context (GdkDrawable  *drawable, 
+                                    CGContextRef  cg_context)
+{
+  if (!GDK_DRAWABLE_IMPL_QUARTZ_GET_CLASS (drawable)->release_context)
+    {
+      g_warning ("%s doesn't implement GdkDrawableImplQuartzClass::release_context()",
+                 G_OBJECT_TYPE_NAME (drawable));
+      return;
+    }
+
+  GDK_DRAWABLE_IMPL_QUARTZ_GET_CLASS (drawable)->release_context (drawable, cg_context);
+}
+
 /* Help preventing "beam sync penalty" where CG makes all graphics code
  * block until the next vsync if we try to flush (including call display on
  * a view) too often. We do this by limiting the manual flushing done
@@ -212,26 +226,6 @@ _gdk_quartz_drawable_flush (GdkDrawable *drawable)
     prev_tv = tv;
 }
 
-void
-gdk_quartz_drawable_release_context (GdkDrawable  *drawable, 
-                                    CGContextRef  cg_context)
-{
-  if (GDK_IS_WINDOW_IMPL_QUARTZ (drawable))
-    {
-      GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (drawable);
-
-      CGContextRestoreGState (cg_context);
-      CGContextSetAllowsAntialiasing (cg_context, TRUE);
-
-      /* See comment in gdk_quartz_drawable_get_context(). */
-      if (window_impl->in_paint_rect_count == 0)
-        {
-          _gdk_quartz_drawable_flush (drawable);
-          [window_impl->view unlockFocus];
-        }
-    }
-}
-
 void
 _gdk_quartz_drawable_finish (GdkDrawable *drawable)
 {
index 52a9bef5d517bd62846cc3e26ba5161dd7971cdf..24d17d83eaf3ade1eda9557b315192cd5409a02a 100644 (file)
@@ -56,6 +56,8 @@ struct _GdkDrawableImplQuartzClass
   /* vtable */
   CGContextRef (*get_context) (GdkDrawable* drawable,
                               gboolean     antialias);
+  void         (*release_context) (GdkDrawable  *drawable,
+                                   CGContextRef  cg_context);
 };
 
 GType        gdk_drawable_impl_quartz_get_type   (void);
index ffdc83bc07c5572c4749cd3130e39c11e4e038f6..6a583476671317353858dc1ca8f40eaa54da7a9d 100644 (file)
@@ -30,6 +30,7 @@
 #include "gdkinputprivate.h"
 
 static gpointer parent_class;
+static gpointer root_window_parent_class;
 
 static GSList   *update_nswindows;
 static gboolean  in_process_all_updates = FALSE;
@@ -141,6 +142,23 @@ gdk_window_impl_quartz_get_context (GdkDrawable *drawable,
   return cg_context;
 }
 
+static void
+gdk_window_impl_quartz_release_context (GdkDrawable  *drawable,
+                                        CGContextRef  cg_context)
+{
+  GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (drawable);
+
+  CGContextRestoreGState (cg_context);
+  CGContextSetAllowsAntialiasing (cg_context, TRUE);
+
+  /* See comment in gdk_quartz_drawable_get_context(). */
+  if (window_impl->in_paint_rect_count == 0)
+    {
+      _gdk_quartz_drawable_flush (drawable);
+      [window_impl->view unlockFocus];
+    }
+}
+
 static void
 check_grab_unmap (GdkWindow *window)
 {
@@ -214,6 +232,7 @@ gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass)
   object_class->finalize = gdk_window_impl_quartz_finalize;
 
   drawable_quartz_class->get_context = gdk_window_impl_quartz_get_context;
+  drawable_quartz_class->release_context = gdk_window_impl_quartz_release_context;
 }
 
 static void
@@ -1009,7 +1028,7 @@ _gdk_windowing_window_init (void)
   _gdk_root = g_object_new (GDK_TYPE_WINDOW, NULL);
 
   private = (GdkWindowObject *)_gdk_root;
-  private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+  private->impl = g_object_new (_gdk_root_window_impl_quartz_get_type (), NULL);
   private->impl_window = private;
   private->visual = gdk_screen_get_system_visual (_gdk_screen);
 
@@ -2968,3 +2987,78 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->translate = _gdk_quartz_window_translate;
   iface->destroy = _gdk_quartz_window_destroy;
 }
+
+
+static CGContextRef
+gdk_root_window_impl_quartz_get_context (GdkDrawable *drawable,
+                                         gboolean     antialias)
+{
+  GdkDrawableImplQuartz *drawable_impl = GDK_DRAWABLE_IMPL_QUARTZ (drawable);
+  CGColorSpaceRef colorspace;
+  CGContextRef cg_context;
+
+  if (GDK_WINDOW_DESTROYED (drawable_impl->wrapper))
+    return NULL;
+
+  /* We do not have the notion of a root window on OS X.  We fake this
+   * by creating a 1x1 bitmap and return a context to that.
+   */
+  colorspace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
+  cg_context = CGBitmapContextCreate (NULL,
+                                      1, 1, 8, 4, colorspace,
+                                      kCGImageAlphaPremultipliedLast);
+  CGColorSpaceRelease (colorspace);
+
+  return cg_context;
+}
+
+static void
+gdk_root_window_impl_quartz_release_context (GdkDrawable  *drawable,
+                                             CGContextRef  cg_context)
+{
+  CGContextRelease (cg_context);
+}
+
+static void
+gdk_root_window_impl_quartz_class_init (GdkRootWindowImplQuartzClass *klass)
+{
+  GdkDrawableImplQuartzClass *drawable_quartz_class = GDK_DRAWABLE_IMPL_QUARTZ_CLASS (klass);
+
+  root_window_parent_class = g_type_class_peek_parent (klass);
+
+  drawable_quartz_class->get_context = gdk_root_window_impl_quartz_get_context;
+  drawable_quartz_class->release_context = gdk_root_window_impl_quartz_release_context;
+}
+
+static void
+gdk_root_window_impl_quartz_init (GdkRootWindowImplQuartz *impl)
+{
+}
+
+GType
+_gdk_root_window_impl_quartz_get_type (void)
+{
+  static GType object_type = 0;
+
+  if (!object_type)
+    {
+      const GTypeInfo object_info =
+        {
+          sizeof (GdkRootWindowImplQuartzClass),
+          (GBaseInitFunc) NULL,
+          (GBaseFinalizeFunc) NULL,
+          (GClassInitFunc) gdk_root_window_impl_quartz_class_init,
+          NULL,           /* class_finalize */
+          NULL,           /* class_data */
+          sizeof (GdkRootWindowImplQuartz),
+          0,              /* n_preallocs */
+          (GInstanceInitFunc) gdk_root_window_impl_quartz_init,
+        };
+
+      object_type = g_type_register_static (GDK_TYPE_WINDOW_IMPL_QUARTZ,
+                                            "GdkRootWindowQuartz",
+                                            &object_info, 0);
+    }
+
+  return object_type;
+}
index c022b991cef1399a49cefdcc1b521afd7d7608d5..b591eebc81b67d1779bb03e8917f6e699477d0a4 100644 (file)
@@ -69,6 +69,33 @@ struct _GdkWindowImplQuartzClass
 
 GType _gdk_window_impl_quartz_get_type (void);
 
+
+/* Root window implementation for Quartz
+ */
+
+typedef struct _GdkRootWindowImplQuartz GdkRootWindowImplQuartz;
+typedef struct _GdkRootWindowImplQuartzClass GdkRootWindowImplQuartzClass;
+
+#define GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ              (_gdk_root_window_impl_quartz_get_type ())
+#define GDK_ROOT_WINDOW_IMPL_QUARTZ(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ, GdkRootWindowImplQuartz))
+#define GDK_ROOT_WINDOW_IMPL_QUARTZ_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ, GdkRootWindowImplQuartzClass))
+#define GDK_IS_ROOT_WINDOW_IMPL_QUARTZ(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ))
+#define GDK_IS_ROOT_WINDOW_IMPL_QUARTZ_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ))
+#define GDK_ROOT_WINDOW_IMPL_QUARTZ_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ, GdkRootWindowImplQuartzClass))
+
+struct _GdkRootWindowImplQuartz
+{
+  GdkWindowImplQuartz parent_instance;
+};
+struct _GdkRootWindowImplQuartzClass 
+{
+  GdkWindowImplQuartzClass parent_class;
+};
+
+GType _gdk_root_window_impl_quartz_get_type (void);
+
+
 G_END_DECLS
 
 #endif /* __GDK_WINDOW_QUARTZ_H__ */